iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 8
1
Modern Web

寫給工程師的 WebGL 學習心得系列 第 8

[WebGL - Day08] GLSL 型別與看懂 Shadertoy 建立時產生的程式

  • 分享至 

  • xImage
  •  

接著來到本系列第二部分:如何寫


GLSL 的變數宣告與 JavaScript 差異很大:

  • 需明確定義型別
  • 沒有轉型,錯了就是錯了
  • Storage Qualifiers

列舉一些變數類型:
void:空
bool:布林
int:整數
float:浮點數

vec22 個浮點數組成的向量
vec33 個浮點數組成的向量
vec44 個浮點數組成的向量

bvec22 個布林組成的向量 // b 是 bool
bvec33 個布林組成的向量
bvec44 個布林組成的向量

ivec22 個整數組成的向量 // i 是 int
ivec33 個整數組成的向量
ivec44 個整數組成的向量

mat2 – 浮點數的 2X2 矩陣
mat3 – 浮點數的 3X3 矩陣
mat4 – 浮點數的 4X4 矩陣


通常 n 個向量有自己的意義,例如:
{r, g, b, a} // 可以是顏色 (colors)
{x, y, z, w} // 可以是座標 (points or normals)
{s, t, p, q} // 也可以是紋理座標 (texture coordinates)

變數的使用方法:

vec4 v = vec4(1.0, 2.0, 3.0, 1.0);
float x = v.x; //1.0
float x1 = v.r; //1.0
float x2 = v[0]; //1.0

vec3 xyz = v.xyz; //vec3(1.0,2.0,3.0)
vec3 xyz1 = vec(v[0],v[1],v[2]); //vec3(1.0,2.0,3.0)
vec3 rgb = v.rgb; //vec3(1.0,2.0,3.0)

vec2 xyzw = v.xyzw; //vec4(1.0,2.0,3.0,1.0);
vec2 rgba = v.rgba; //vec4(1.0,2.0,3.0,1.0);

回到 Shadertoy 的程式碼:
Shadertoy

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;

    // Time varying pixel color
    vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));

    // Output to screen
    fragColor = vec4(col,1.0);
}

已可閱讀程式碼,但還不提上色的原理:

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = fragCoord/iResolution.xy;
}

fragCoord 是一個 vec2 的輸入,而 iResolution 是 shadertoy 內建的 input
(uniform vec3 iResolution)

iResolution 是 vec3
為了讓 vec2 的 uv 不出錯,fragCoord(vec2) 需與 float 或是 vec2 運算

fragCoord/iResolution.xy; 等同於
fragCoord/vec2(iResolution.x, iResolution.y);

uv 是 vec2,因此可以用 uv.xuv.y 來取值


vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
  • 註1.
    col 是 3 個浮點數組成的向量,在運算的時候也必須使用 3 個浮點數做運算
    也因此會出現 uv.xyx,看似奇怪但並非程式碼的問題

uv.xyx 等同於 vec3(uv.x, uv.y, uv.x)

  • 註2.
    由於變數可以用 {x,y,z,w} 或 {r, g, b, a}
    因此改成 uv.rgr 就程式上來說可以的,但是會覺得有些不自在
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    fragColor = vec4(col,1.0);
}

輸出的 fragColor 是 vec4,需要 4 個浮點數
col 是 vec3,放到 vec4 時要補上最後一個值


關於型別

踩過覺得比較特別的是 floatint
float 一定要有小數點,而 int 一定不能有小數點

float a1=1.0; // 沒問題,這是浮點數
float a2=1.; // 沒問題,後面有一個點
float a3=1; // 有問題,不能是整數

int a4 = 1;
float b1 = float(a4); // 轉到正確的型別即可

Storage Qualifiers

Storage Qualifiers 是在一些變數前會看到的字:

  • [none]
  • const
  • uniform
  • attribute
  • varying
// Storage Qualifiers 會在變數型別的前面:
attribute vec2 aPosition;
varying vec2 vUv;
uniform vec2 texelSize;

這些是另一些看不太懂的東西,
需要配著 WebGL Pipeline
WebGL Pipeline

在此,我們更專注在 vertex shader 與 fragment shader、箭頭方向
WebGL Pipeline

  • attribute:整個 WebGL 的 vertex 資訊
  • uniform:類似全域變數,到處皆可用
  • varyings:vertex shader 輸出,fragment shader 讀取
    (變數名需相同)
  • const:如其他語言,只能讀取
  • [none]:預設沒有 Storage Qualifiers

也因為 Storage Qualifiers 的特性,
JavaScript 實際上能控制或帶進 Shader 的只有
attributeuniform 兩種參數


所有變數都要加上 Storage Qualifiers 嗎?

不用,Shader 自己用的時候就不用


上一篇
[WebGL - Day07] Shadertoy 網站與 YouTube 頻道:The Art of Code
下一篇
[WebGL - Day09] Shader 的寫法規定與通則
系列文
寫給工程師的 WebGL 學習心得30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
King Tzeng
iT邦新手 3 級 ‧ 2019-09-24 23:51:57

好可怕的世界.... /images/emoticon/emoticon16.gif

再忍個幾天就到比較神奇的地方了 QQ

0
阿展展展
iT邦好手 1 級 ‧ 2020-01-29 00:27:09

數 數學 /images/emoticon/emoticon26.gif

我要留言

立即登入留言